package concurrency.part1.task1;


import concurrency.Function;

public class Main {
    public static final Function sin = new Function() {
        @Override
        public double call(double x) {
            return Math.sin(x);
        }
    };

    public static void main(String[] args) throws InterruptedException {
        int n = 20000;
        int maxRank=8;
        System.out.println("Sum of sin(x) where x from " + -n + " to " + n + " on is: " + SeriesEval.eval(sin, -n,n,1, maxRank) + " " + n);
    }
}


class SeriesEval extends Thread {
    private Function function;
    private double startX, endX, stepX;
    private double result;

    private SeriesEval(Function function, double startX, double endX, double stepX) {
        this.function = function;
        this.startX = startX;
        this.endX = endX;
        this.stepX = stepX;
    }

    public static double eval(Function f, double startX, double endX, double step, int maxRank) {
        double taskStep = (endX-startX)/maxRank;
        SeriesEval tasks[] = new SeriesEval[maxRank];
        for (int i = 0; i < maxRank; i++, startX += taskStep) {
            tasks[i] = new SeriesEval(f, startX, i == maxRank - 1 ? Math.max(startX+taskStep,endX+step) : startX + taskStep, step);
            tasks[i].start();
        }

        double sum = 0;
        for (SeriesEval task : tasks) {
            try {
                task.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            sum += task.getResult();
        }
        return sum;
    }

    @Override
    public void run() {
        double sum = 0;
        for (double x = startX; x < endX; x += stepX) {
            sum += function.call(x);
        }
        result = sum;
    }

    private double getResult() {
        return result;
    }
}